using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using CPlatePrintSys.DataAccess.Context;
using CPlatePrintSys.Infrastructure.Repositories;
using CPlatePrintSys.Domain.Models;
using CPlatePrintSys.Infrastructure;

namespace CPlatePrintSys.DataAccess.Repositories
{
    public class UserRepository : IUserRepository
    {
        private readonly CPlateDbContext _context;

        public UserRepository(CPlateDbContext context)
        {
            _context = context;
        }

        public async Task<User> GetByIdAsync(object id)
        {
            return await _context.Users.FindAsync(id);
        }

        public async Task<IEnumerable<User>> GetAllAsync()
        {
            return await _context.Users.ToListAsync();
        }

        public async Task<User> AddAsync(User entity)
        {
            entity.CreatedAt = DateTime.Now;
            entity.UpdatedAt = DateTime.Now;
            entity.Password = Utilities.HashPassword(entity.Password);
            
            _context.Users.Add(entity);
            await _context.SaveChangesAsync();
            return entity;
        }

        public async Task UpdateAsync(User entity)
        {
            var dbUser = await _context.Users.FindAsync(entity.Id);
            if (dbUser == null)
                throw new Exception("用户不存在");

            // 只赋值需要更新的字段
            dbUser.Username = entity.Username;
            dbUser.Password = entity.Password;
            dbUser.JobNumber = entity.JobNumber;
            dbUser.FullName = entity.FullName;
            dbUser.Role = entity.Role;
            dbUser.IsActive = entity.IsActive;
            dbUser.UpdatedAt = DateTime.Now;
            dbUser.LastLoginAt = entity.LastLoginAt;

            await _context.SaveChangesAsync();
        }

        public async Task DeleteAsync(object id)
        {
            var user = await _context.Users.FindAsync(id);
            if (user != null)
            {
                _context.Users.Remove(user);
                await _context.SaveChangesAsync();
            }
        }

        public async Task<IEnumerable<User>> FindAsync(Expression<Func<User, bool>> predicate)
        {
            return await _context.Users.Where(predicate).ToListAsync();
        }

        public async Task<int> CountAsync(Expression<Func<User, bool>> predicate = null)
        {
            if (predicate == null)
                return await _context.Users.CountAsync();
            return await _context.Users.CountAsync(predicate);
        }

        public async Task<User> GetByUsernameAsync(string username)
        {
            return await _context.Users.FirstOrDefaultAsync(u => u.Username == username);
        }

        public async Task<User> GetByJobNumberAsync(string jobNumber)
        {
            return await _context.Users.FirstOrDefaultAsync(u => u.JobNumber == jobNumber);
        }

        public async Task<bool> IsUsernameExistsAsync(string username)
        {
            return await _context.Users.AnyAsync(u => u.Username == username);
        }

        public async Task<bool> IsJobNumberExistsAsync(string jobNumber)
        {
            return await _context.Users.AnyAsync(u => u.JobNumber == jobNumber);
        }

        public async Task UpdateLastLoginAsync(int userId)
        {
            var user = await _context.Users.FindAsync(userId);
            if (user != null)
            {
                user.LastLoginAt = DateTime.Now;
                await _context.SaveChangesAsync();
            }
        }

        public async Task<bool> ValidateCredentialsAsync(string username, string password)
        {
            var user = await _context.Users.FirstOrDefaultAsync(u => u.Username == username && u.IsActive);
            if (user == null)
                return false;

            return VerifyPassword(password, user.Password);
        }


        private bool VerifyPassword(string inputPassword, string hashedPassword)
        {
            var inputHash = Utilities.HashPassword(inputPassword);
            return inputHash == hashedPassword;
        }
    }
} 